#ifndef VIDEORECORDER_MPP_H
#define VIDEORECORDER_MPP_H

#include <rockchip/rk_mpi.h>

#include <QFile>
#include <QObject>
#include <memory>
#include <opencv2/opencv.hpp>

#include "baserecorder.h"

#define MPP_ALIGN(x, a) (((x) + (a)-1) & ~((a)-1))

/**
 * @brief 配置参数集合
 *
 */
struct EncoderConf {
  int frame_width = 1920;
  int frame_height = 1080;

  int hor_stride = MPP_ALIGN(frame_width, 1);
  int ver_stride = MPP_ALIGN(frame_height, 1);

  MppFrameFormat format = MppFrameFormat::MPP_FMT_YUV420P;
  MppCodingType codecype = MppCodingType::MPP_VIDEO_CodingAVC;

  int bps =
      15552000;  // CBR 模式下的目标码率。 cfg_frame_width * cfg_frame_height /
                 // 8 * (cfg_fps_out_num / cfg_fps_out_den);（15552000）
  int bps_max = 0;  // VBR 模式下的最高码率。
  int bps_min = 0;  // VBR 模式下的最低码率。
  int rc_mode =
      MppEncRcMode::MPP_ENC_RC_MODE_VBR;  // 码率控制模式:CBR 为 Constant Bit
                                          // Rate，固定码率模式,VBR 为 Variable
                                          // Bit Rate，可变码率模式.

  int gop_mode = 0;
  int gop_len = 0;
  int vi_len = 0;
  int fps_in_flex = 0;  // 0为固定， 1 不固定
  int fps_in_den = 1;
  int fps_in_num = 60;
  int fps_out_flex = 0;
  int fps_out_den = 1;
  int fps_out_num = 60;
  int frame_size = 0;
  int header_size = 0;
};

/**
 * @brief 编码器使用mpp
 *
 */
class VideoRecorder_MPP : public BaseRecorder {
  Q_OBJECT
 public:
  explicit VideoRecorder_MPP(QObject* parent = nullptr);

  ~VideoRecorder_MPP();

  // 初始化
  bool init() override;

  // 反初始化
  void uninit();

  // 打开输出文件
  bool openFile(const QString& basename) override;

 public slots:
  // 图片接收
  void onImage(std::shared_ptr<QImage> img) override;

 private:
  // 设置配置参数的数值
  void initConf();

  // 设置配置
  bool setupConf();

  // QImage转换成yuv
  bool image2Yuv420(std::shared_ptr<QImage> img, cv::Mat* yuvFrame);

  // 数据写入文件
  bool writeToFile(const cv::Mat& yuvFrame);

  // 初始化MppFrame
  bool initFrame();

 private:
  MppApi* m_pMpi{nullptr};
  MppCtx m_ctx;

  // 配置
  EncoderConf m_encoderConf;

  MppEncCfg m_enc_cfg{nullptr};

  // input / output
  MppBufferGroup buf_grp;
  MppBuffer frm_buf;
  MppBuffer pkt_buf;

  MppFrame m_frame{nullptr};

  MppEncSeiMode sei_mode{MPP_ENC_SEI_MODE_ONE_FRAME};
  MppEncHeaderMode header_mode{MPP_ENC_HEADER_MODE_EACH_IDR};

  // 输出文件
  QFile m_outFile;

 signals:
};

#endif  // VIDEORECORDER_MPP_H
